home *** CD-ROM | disk | FTP | other *** search
/ Skunkware 5 / Skunkware 5.iso / src / Games / xsokoban / play.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-05-03  |  6.8 KB  |  236 lines

  1. #include <ctype.h>
  2. #include "sokoban.h"
  3.  
  4. /* defining the types of move */
  5. #define MOVE         1
  6. #define PUSH         2
  7. #define SAVE         3
  8. #define UNSAVE         4
  9. #define STOREMOVE     5
  10. #define STOREPUSH     6
  11.  
  12. /* defines for control characters */
  13. #define CNTL_L        '\014'
  14. #define CNTL_K        '\013'
  15. #define CNTL_H        '\010'
  16. #define CNTL_J        '\012'
  17. #define CNTL_R        '\022'
  18. #define CNTL_U        '\025'
  19.  
  20. extern char  map[MAXROW+1][MAXCOL+1];
  21. extern short rows, cols, level, moves, pushes, savepack, packets;
  22. extern short scorelevel, scoremoves, scorepushes;
  23. extern POS   ppos;
  24.  
  25. static POS   tpos1,           /* testpos1: 1 pos. over/under/left/right */
  26.              tpos2,           /* testpos2: 2 pos.  "                    */
  27.              lastppos,           /* the last player position (for undo)    */
  28.              lasttpos1, lasttpos2; /* last test positions (for undo)         */
  29. static char lppc, ltp1c, ltp2c;    /* the char for the above pos. (for undo) */
  30. static short action, lastaction;
  31.  
  32. /** For the temporary save **/
  33. static char  tmp_map[MAXROW+1][MAXCOL+1];
  34. static short tmp_pushes, tmp_moves, tmp_savepack;
  35. static POS   tmp_ppos;
  36.  
  37. short play() {
  38.  
  39.    short c;
  40.    short ret;
  41.    short undolock = 1;        /* locked for undo */
  42.    
  43.    clearscreen();
  44.    showscreen();
  45.    tmpsave();
  46.    ret = 0;
  47.    while( ret == 0) {
  48.       switch( (c = event_loop())) {
  49.      case 'q':    /* quit the game                     */
  50.                   ret = E_ENDGAME; 
  51.                   break;
  52.      case 's':    /* save the games                    */
  53.               if( (ret = savegame()) == 0)
  54.              ret = E_SAVED;
  55.               break;
  56.      case '?':    /* show the help file                */
  57.               showhelp();
  58.               redisp_screen();
  59.               break;
  60.      case CNTL_R: /* refresh the screen                 */
  61.               redisp_screen();
  62.               break;
  63.      case 'c':    /* temporary save                    */
  64.               tmpsave();
  65.               break;
  66.      case CNTL_U: /* reset to temporary save             */
  67.               tmpreset();
  68.               undolock = 1;
  69.               showscreen();
  70.               break;
  71.      case 'U':    /* undo this level                 */
  72.               moves = pushes = 0;
  73.               if( (ret = readscreen()) == 0) {
  74.                  showscreen();
  75.              undolock = 1;
  76.               }
  77.               break;
  78.      case 'u':    /* undo last move                 */
  79.               if( ! undolock) {
  80.                  undomove();
  81.                  undolock = 1;
  82.               }
  83.               break;
  84.      case 'k':    /* up                         */
  85.      case 'K':    /* run up                     */
  86.      case CNTL_K: /* run up, stop before object             */
  87.      case 'j':    /* down                         */
  88.      case 'J':    /* run down                     */
  89.      case CNTL_J: /* run down, stop before object             */
  90.      case 'l':    /* right                         */
  91.      case 'L':    /* run right                     */
  92.      case CNTL_L: /* run right, stop before object             */
  93.      case 'h':    /* left                         */
  94.      case 'H':    /* run left                     */
  95.      case CNTL_H: /* run left, stop before object             */
  96.               do {
  97.                  if( (action = testmove( c)) != 0) {
  98.                 lastaction = action;
  99.                     lastppos.x = ppos.x; lastppos.y = ppos.y;
  100.                     lppc = map[ppos.x][ppos.y];
  101.                     lasttpos1.x = tpos1.x; lasttpos1.y = tpos1.y; 
  102.                     ltp1c = map[tpos1.x][tpos1.y];
  103.                     lasttpos2.x = tpos2.x; lasttpos2.y = tpos2.y; 
  104.                     ltp2c = map[tpos2.x][tpos2.y];
  105.                     domove( lastaction); 
  106.                     undolock = 0;
  107.                  }
  108.               } while( (action != 0) && (! islower( c))
  109.                   && (packets != savepack));
  110.               break;
  111.      default:     helpmessage(); break;
  112.       }
  113.       if( (ret == 0) && (packets == savepack)) {
  114.      scorelevel = level;
  115.      scoremoves = moves;
  116.      scorepushes = pushes;
  117.      break;
  118.       }
  119.    }
  120.    return( ret);
  121. }
  122.  
  123. testmove( action)
  124. register short action;
  125. {
  126.    register short ret;
  127.    register char  tc;
  128.    register short stop_at_object;
  129.  
  130.    if( (stop_at_object = iscntrl( action))) action = action + 'A' - 1;
  131.    action = (isupper( action)) ? tolower( action) : action;
  132.    if( (action == 'k') || (action == 'j')) {
  133.       tpos1.x = (action == 'k') ? ppos.x-1 : ppos.x+1;
  134.       tpos2.x = (action == 'k') ? ppos.x-2 : ppos.x+2;
  135.       tpos1.y = tpos2.y = ppos.y;
  136.    }
  137.    else {
  138.       tpos1.y = (action == 'h') ? ppos.y-1 : ppos.y+1;
  139.       tpos2.y = (action == 'h') ? ppos.y-2 : ppos.y+2;
  140.       tpos1.x = tpos2.x = ppos.x;
  141.    }
  142.    tc = map[tpos1.x][tpos1.y];
  143.    if( (tc == packet) || (tc == save)) {
  144.       if( ! stop_at_object) {
  145.          if( map[tpos2.x][tpos2.y] == ground)
  146.             ret = (tc == save) ? UNSAVE : PUSH;
  147.          else if( map[tpos2.x][tpos2.y] == store)
  148.             ret = (tc == save) ? STOREPUSH : SAVE;
  149.          else ret = 0;
  150.       }
  151.       else ret = 0;
  152.    }
  153.    else if( tc == ground)
  154.       ret = MOVE;
  155.    else if( tc == store)
  156.       ret = STOREMOVE;
  157.    else ret = 0;
  158.    return( ret);
  159. }
  160.  
  161. domove( moveaction) 
  162. register short moveaction;
  163. {
  164.    map[ppos.x][ppos.y] = (map[ppos.x][ppos.y] == player) 
  165.                    ? ground
  166.                    : store;
  167.    switch( moveaction) {
  168.       case MOVE:      map[tpos1.x][tpos1.y] = player;     break;
  169.       case STOREMOVE: map[tpos1.x][tpos1.y] = playerstore;     break;
  170.       case PUSH:      map[tpos2.x][tpos2.y] = map[tpos1.x][tpos1.y];
  171.               map[tpos1.x][tpos1.y] = player;    
  172.               pushes++;                        break;
  173.       case UNSAVE:    map[tpos2.x][tpos2.y] = packet;
  174.               map[tpos1.x][tpos1.y] = playerstore;        
  175.               pushes++; savepack--;                 break;
  176.       case SAVE:      map[tpos2.x][tpos2.y] = save;
  177.               map[tpos1.x][tpos1.y] = player;            
  178.               savepack++; pushes++;                break;
  179.       case STOREPUSH: map[tpos2.x][tpos2.y] = save;
  180.               map[tpos1.x][tpos1.y] = playerstore;        
  181.               pushes++;                        break;
  182.    }
  183.    moves++;
  184.    dispmoves(); disppushes(); dispsave();
  185.    mapchar( map[ppos.x][ppos.y], ppos.x, ppos.y);
  186.    mapchar( map[tpos1.x][tpos1.y], tpos1.x, tpos1.y);
  187.    mapchar( map[tpos2.x][tpos2.y], tpos2.x, tpos2.y);
  188.    redisp_screen();
  189.    ppos.x = tpos1.x; ppos.y = tpos1.y;
  190. }
  191.  
  192. undomove() {
  193.  
  194.    map[lastppos.x][lastppos.y] = lppc;
  195.    map[lasttpos1.x][lasttpos1.y] = ltp1c;
  196.    map[lasttpos2.x][lasttpos2.y] = ltp2c;
  197.    ppos.x = lastppos.x; ppos.y = lastppos.y;
  198.    switch( lastaction) {
  199.       case MOVE:      moves--;                break;
  200.       case STOREMOVE: moves--;                break;
  201.       case PUSH:      moves--; pushes--;        break;
  202.       case UNSAVE:    moves--; pushes--; savepack++;    break;
  203.       case SAVE:      moves--; pushes--; savepack--;    break;
  204.       case STOREPUSH: moves--; pushes--;        break;
  205.    }
  206.    dispmoves(); disppushes(); dispsave();
  207.    mapchar( map[ppos.x][ppos.y], ppos.x, ppos.y);
  208.    mapchar( map[lasttpos1.x][lasttpos1.y], lasttpos1.x, lasttpos1.y);
  209.    mapchar( map[lasttpos2.x][lasttpos2.y], lasttpos2.x, lasttpos2.y);
  210.    redisp_screen();
  211. }
  212.  
  213. tmpsave() {
  214.  
  215.    register short i, j;
  216.  
  217.    for( i = 0; i < rows; i++) for( j = 0; j < cols; j++)
  218.       tmp_map[i][j] = map[i][j];
  219.    tmp_pushes = pushes;
  220.    tmp_moves = moves;
  221.    tmp_savepack = savepack;
  222.    tmp_ppos.x = ppos.x; tmp_ppos.y = ppos.y;
  223. }
  224.  
  225. tmpreset() {
  226.  
  227.    register short i, j;
  228.  
  229.    for( i = 0; i < rows; i++) for( j = 0; j < cols; j++)
  230.       map[i][j] = tmp_map[i][j];
  231.    pushes = tmp_pushes;
  232.    moves = tmp_moves;
  233.    savepack = tmp_savepack;
  234.    ppos.x = tmp_ppos.x; ppos.y = tmp_ppos.y;
  235. }
  236.